﻿Imports System.Collections
Imports System.Text
Imports System.IO
Imports System.Resources
Imports System.Windows
Imports System.Windows.Interop
Imports System.Windows.Media
Imports System.Windows.Media.Imaging
Imports Microsoft.VisualStudio.Text
Imports System.Reflection
Imports System.Xml.Serialization
Imports System.Xml

Namespace Microsoft.VisualStudio.ImageInsertion
	''' <summary>
	''' Saves and retrieves image adornements from a repository.
	''' </summary>
	Friend Class ImageAdornmentRepositoryService
		Private textBuffer As ITextBuffer
        Private mImages As New List(Of ImageAdornment)

        Friend Sub New(ByVal textBuffer As ITextBuffer)
            Me.textBuffer = textBuffer

            Dim textDocument = textBuffer.Properties.GetProperty(Of ITextDocument)(GetType(ITextDocument))
            Me.RepositoryFilename = Path.ChangeExtension(textDocument.FilePath, ".Images.resx")
        End Sub

        Friend ReadOnly Property Images As IList(Of ImageAdornment)
            Get
                Return Me.mImages
            End Get
        End Property

        Friend Sub EnsureRepositoryFileExists()
            If Not File.Exists(Me.RepositoryFilename) Then
                Using writer = New ResourceWriter(Me.RepositoryFilename)
                    writer.Generate()
                End Using
            End If
        End Sub

        Friend Sub Save()
            If Not File.Exists(Me.RepositoryFilename) AndAlso Me.mImages.Count = 0 Then Return

            ' Write the images to the repository file
            Using writer = New ResourceWriter(Me.RepositoryFilename)
                For Each info As ImageAdornmentInfo In Me.mImages.Select(Function(image) image.Info)
                    writer.AddResource(info.Id, info)
                Next info

                writer.Generate()
            End Using
        End Sub

        Friend Sub Load()
            If File.Exists(Me.RepositoryFilename) Then
                Using reader = New ResourceReader(Me.RepositoryFilename)
                    Try
                        AddHandler AppDomain.CurrentDomain.AssemblyResolve, AddressOf OnCurrentAppDomainAssemblyResolve

                        For Each entry As DictionaryEntry In reader
                            Dim info = TryCast(entry.Value, ImageAdornmentInfo)
                            ' Convert the bitmap
                            Dim imageSource = GetImageSourceFromBitmap(info.Bitmap)

                            Dim imageAdornment As New ImageAdornment(Me.textBuffer.CurrentSnapshot, info, imageSource)

                            Add(imageAdornment)
                        Next entry
                    Finally
                        RemoveHandler AppDomain.CurrentDomain.AssemblyResolve, AddressOf OnCurrentAppDomainAssemblyResolve
                    End Try
                End Using
            End If
        End Sub

        Private Function OnCurrentAppDomainAssemblyResolve(ByVal sender As Object, ByVal e As ResolveEventArgs) As System.Reflection.Assembly
            If e.Name = Me.GetType().Assembly.FullName Then
                Return Me.GetType().Assembly
            End If

            Return Nothing
        End Function

        ''' <summary>
        '''  Adds an image adornment to the repository
        ''' </summary>
        ''' <param name="imageAdornment"></param>
        Friend Sub Add(ByVal imageAdornment As ImageAdornment)
            If imageAdornment IsNot Nothing AndAlso (Not Me.mImages.Contains(imageAdornment)) Then
                Me.mImages.Add(imageAdornment)
            End If
        End Sub

        ''' <summary>
        ''' Removes an image adornement form the repository
        ''' </summary>
        ''' <param name="imageAdornment"></param>
        Friend Sub Remove(ByVal imageAdornment As ImageAdornment)
            If imageAdornment IsNot Nothing AndAlso Me.mImages.Contains(imageAdornment) Then
                Me.mImages.Remove(imageAdornment)
            End If
        End Sub

		Private Shared Function GetImageSourceFromBitmap(ByVal source As System.Drawing.Bitmap) As ImageSource
			' converts the bitmap to image source
			Return Imaging.CreateBitmapSourceFromHBitmap(source.GetHbitmap(), IntPtr.Zero, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions())
		End Function

		''' <summary>
		''' Gets the repository filename
		''' </summary>
        Friend Property RepositoryFilename As String
    End Class
End Namespace